//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<XCtrls.h>
///	@path	~/src/gui/xgui/
///	@date	2008/05/29
///	@desc	.

#pragma once

#include "xeres.h"

#include "gui/IGuiControl.h"
#include "gui/style/style.h"
#include "gui/style/ext_style.h"
#include "gui/style/StyleText.h"
#include "gui/image/IBitmap.h"

#include "gui/xgui/XButton.h"
#include "gui/xgui/XImage.h"
#include "gui/xgui/XStatic.h"

namespace xeres {

	/*! 
		\class	XHolder
		\brief	Holds parent and moves it.
	*/
	class XHolder : public IGuiControl
	{
	public:

		/// \ctor
		XHolder( void );

		/// \ctor
		XHolder( const Rect<int>& placement );

		/// \dtor
		virtual ~XHolder( void );

		DECL_IOBJECT_CLASS_DYNAMIC( XHolder , IGuiControl );

	public:

		/// \brief	Can have focus.
		virtual bool CanHaveFocus( void ) const;

		/// \name Message Passing
		//@{

		///	\brief	Process mouse input message.
		virtual HandleInput OnMouseInput( Updater& updater );

		//@}

	private:

		// @data
		Pair<int>	m_lastPos;
	};

	/*! 
		\class	XTitle
		\brief	Simple title control.
	*/
	class XTitle : public XHolder , public GuiSyleComp<CGuiStyle>
	{
	public:

		/// \ctor
		XTitle( void );

		/// \ctor
		XTitle( const WString& text , const Rect<int>& placement );

		/// \dtor
		virtual ~XTitle( void );

		DECL_IOBJECT_CLASS_DYNAMIC( XTitle , XHolder );

	public:

		/// \brief	Set button text.
		void SetText( const WString& text );

		/// \brief	Get button text.
		const WString& GetText( void ) const { return m_title.GetString(); }

		/// \brief	Get title text style.
		RefWeak<CGuiStyle> GetStyle( void );

		/// \name Message Passing
		//@{

		///	\brief	Process key input message.
		virtual HandleInput OnKeyInput( Updater& updater );

		///	\brief	Process mouse input message.
		virtual HandleInput OnMouseInput( Updater& updater );

		/// \brief	Call when control is about to enable or disable.
		virtual void OnEnable( bool enable );

		/// \brief	Call when focus is about to change.
		virtual void OnFocus( bool focusing );

		/// \brief	Call when mouse over control.
		virtual void OnMouseOver( bool hovering );

		//@}

		/// \name Presentation Manipulation
		//@{

		/// \brief	Draw XGUI component to composition.
		virtual void Draw( Composition& composition );

		//@}

	private:

		/// \brief	Change style call.
		void ChangeStyle( void );

		//@ data
		StyleText	m_title;
	};

	/*! 
	.<-----|
	.      |
	.      |
pos |<--|  |
	|   |  |
	|  page|
	|   |  |
	|<--|  |
	.      |
	.  (range+page)
	.      |
	.      |
	.      |
	.      |
	.<-----|
	*/

	/*! 
		\class	IScrollBar
		\brief
	*/
	class IScrollBar : public IGuiControl
	{
	public:

		/// \ctor
		IScrollBar( void );

		/// \dtor
		virtual ~IScrollBar( void );

		DECL_IOBJECT_INTERFACE( IScrollBar , IGuiControl );

	public:

		/// \name	Message Passing
		//@{

		///	\brief	Process key input message.
		virtual HandleInput OnKeyInput( Updater& updater );

		///	\brief	Process mouse input message.
		virtual HandleInput OnMouseInput( Updater& updater );

		//@}

	protected:

		/// \brief	Get scroll range.
		int GetScrollRange( void ) const;

		/// \brief	Set scroll range.
		void SetScrollRange( int range );

		/// \brief	Get scroll pos.
		int GetScrollPos( void ) const;

		/// \brief	Set scroll pos.
		void SetScrollPos( int pos );

		/// \name	Scroll Bar Interface
		//@{

		/// \brief	Determine if in bar.
		virtual bool HitTestBar( const Pair<int>& pt ) = 0;

		/// \brief	Get local scroll length.
		virtual int GetScrollLength( void ) = 0;

		/// \brief	On drag scroll bar.
		virtual int OnDragBar( const Pair<int>& diff ) = 0;

		/// \brief	On click blank space of bar.
		virtual int OnClickBlank( const Pair<int>& pos ) = 0;

		/// \brief	On set scroll range.
		virtual void OnSetScrollRange( void ) = 0;

		/// \brief	On set scroll pos.
		virtual void OnSetScrollPos( void ) = 0;

		//@}

	protected:

		//@ data
		int				m_scrollPos;
		int				m_scrollRange;

		// tags
		bool			m_inBar;
		bool			m_scrolling;
		bool			m_spare[2];

		// dragging last position.
		Pair<int>		m_lastPos;
	};

	/*! 
		\class	IScrollBarVertical
		\brief
	*/
	class IScrollBarVertical : public IScrollBar
	{
	public:

		/// \ctor
		IScrollBarVertical( void );

		DECL_IOBJECT_INTERFACE( IScrollBarVertical , IScrollBar );

		/// \brief	On drag scroll bar.
		virtual int OnDragBar( const Pair<int>& diff );

		/// \brief	Set scroll range.
		virtual void SetRange( float range , float page ) = 0;

		/// \brief	Set scroll pos.
		virtual void SetPos( float pos ) = 0;
	};

	/*! 
		\class	IScrollBarHorizontal
		\brief
	*/
	class IScrollBarHorizontal : public IScrollBar
	{
	public:

		/// \ctor
		IScrollBarHorizontal( void );

		DECL_IOBJECT_INTERFACE( IScrollBarHorizontal , IScrollBar );

		/// \brief	On drag scroll bar.
		virtual int OnDragBar( const Pair<int>& diff );
	};

	/*! 
		\class	XScrollBarVertical
		\brief
	*/
	class XScrollBarVertical : public IScrollBarVertical
	{
	public:

		/// \ctor
		XScrollBarVertical( void );

		/// \dtor
		virtual ~XScrollBarVertical( void );

		DECL_IOBJECT_CLASS_DYNAMIC( XScrollBarVertical , IScrollBarVertical );

	public:

		/// \brief	Set scroll range.
		virtual void SetRange( float range , float page );

		/// \brief	Set scroll pos.
		virtual void SetPos( float pos );

		/// \brief	Call when close window.
		virtual void OnClose( void );

		/// \brief	Call when size changed.
		virtual void OnSize( void );

		/// \name	Scroll Bar Interface
		//@{

		/// \brief	Determine if in bar.
		virtual bool HitTestBar( const Pair<int>& pt );

		/// \brief	Get local scroll length.
		virtual int GetScrollLength( void );

		/// \brief	On drag scroll bar.
		virtual int OnDragBar( const Pair<int>& diff );

		/// \brief	On click blank space of bar.
		virtual int OnClickBlank( const Pair<int>& pos );

		/// \brief	On set scroll range.
		virtual void OnSetScrollRange( void );

		/// \brief	On set scroll pos.
		virtual void OnSetScrollPos( void );

		//@}

		/// \name Presentation Manipulation
		//@{

		/// \brief	Tick update.
		virtual void Tick( Updater& updater , float dTime );

		/// \brief	Draw XGUI component to composition.
		virtual void Draw( Composition& composition );

		//@}

		/// \brief	Set scroll call.
		void SetScrollCall( function<void(float)> scroll_call ) { m_onScrollCall = scroll_call; }

	private:

		//@ data
		int					m_headReserve;
		int					m_tailReserve;

		float				m_pos;
		float				m_range;
		float				m_page;

		Rect<int>			m_scrollRegion;
		Rect<int>			m_scrollBarRect;

		function<void(float)> m_onScrollCall;
	};

	/*! 
		\class	XScrollBarHorizontal
		\brief
	*/
	class XScrollBarHorizontal : public IScrollBarHorizontal
	{
	public:

		/// \ctor
		XScrollBarHorizontal( void );

		/// \dtor
		virtual ~XScrollBarHorizontal( void );

		DECL_IOBJECT_CLASS_DYNAMIC( XScrollBarHorizontal , IScrollBarHorizontal );

	public:

		/// \brief	Set scroll range.
		virtual void SetRange( float range , float page );

		/// \brief	Set scroll pos.
		virtual void SetPos( float pos );

		/// \brief	Call when close window.
		virtual void OnClose( void );

		/// \brief	Call when size changed.
		virtual void OnSize( void );

		/// \name	Scroll Bar Interface
		//@{

		/// \brief	Determine if in bar.
		virtual bool HitTestBar( const Pair<int>& pt );

		/// \brief	Get local scroll length.
		virtual int GetScrollLength( void );

		/// \brief	On drag scroll bar.
		virtual int OnDragBar( const Pair<int>& diff );

		/// \brief	On click blank space of bar.
		virtual int OnClickBlank( const Pair<int>& pos );

		/// \brief	On set scroll range.
		virtual void OnSetScrollRange( void );

		/// \brief	On set scroll pos.
		virtual void OnSetScrollPos( void );

		//@}

		/// \name Presentation Manipulation
		//@{

		/// \brief	Tick update.
		virtual void Tick( Updater& updater , float dTime );

		/// \brief	Draw XGUI component to composition.
		virtual void Draw( Composition& composition );

		//@}

		/// \brief	Set scroll call.
		void SetScrollCall( function<void(float)> scroll_call ) { m_onScrollCall = scroll_call; }

	private:

		//@ data
		int					m_headReserve;
		int					m_tailReserve;

		float				m_pos;
		float				m_range;
		float				m_page;

		Rect<int>			m_scrollRegion;
		Rect<int>			m_scrollBarRect;

		function<void(float)> m_onScrollCall;
	};

} // namespace xeres
